﻿#pragma once
#include "base/core/singleton.h"
#include "Common/MessageDispatch/IMessageDispatch.h"
#include <unordered_map>
#include "Common/ServerDefine.h"
#include "Common/AccountDefine.h"
#include "ProtoBuffer/ComProtocol.pb.h"
#include "ProtoBuffer/ClientToLogic.pb.h"
#include <queue>

struct UidGameInfo;
struct CidCurAndLastScene;
struct ClientIdAndLogicId;
class CenterAccountMgr : public ManualSingleton<CenterAccountMgr>,
				  public IDBProxyMessageHandler,
				  public IServerMessageHandler,
				  public IClientMessageHandler
{
	friend class ManualSingleton<CenterAccountMgr>;
	typedef unordered_map<uint32_t, UidGameInfo>  CID_GAME_MAP;  //clientid --> UidGameInfo
	typedef unordered_map<uint32_t, uint32_t>  UID_GAME_MAP;  //uid-->clientid
	typedef unordered_map<CharIDType, ClientIdAndLogicId>  CID_CLIENT_LOGIC_ID_MAP;

protected:

	UID_GAME_MAP   m_uidMap; // uid - clientid
	UID_GAME_MAP   m_logoutUidMap; //正在离线列表 uid -clientid
	CID_GAME_MAP   m_clientIdMap; // clientid - UidGameInfo
	CID_CLIENT_LOGIC_ID_MAP m_cidClientLogicIdMap;

	// auto increase db request id
	uint32_t m_dbreq;
	//
	uint32_t NewReqId();

	bool     m_bloginOpen;
		 
	// recv from client and send to chardb
	bool LoginGateReq(uint32_t clientId, RECV_PACKAGE& package);
	bool CreateCharacterReq(uint32_t clientId, RECV_PACKAGE& package);
	bool DelCharacterReq(uint32_t clientId, RECV_PACKAGE& package);
	bool DelCharacterCancelReq(uint32_t clientId, RECV_PACKAGE& package);
	bool CreateCharacterToDBReq(uint32_t uid, uint32_t clientId, ClientCreateCharacterReq& createCharacter, uint32_t channelId);

	//recv client and send logic
	bool EnterGameReq(uint32_t clientId, RECV_PACKAGE& package);
	bool LeaveGameReq(uint32_t clientId, RECV_PACKAGE& package);
	bool ReConnectReq(uint32_t clientId, RECV_PACKAGE& package);

	bool NotifyLogicLeave(CharIDType cid, uint32_t uid); 

	//recv logic and send client
	bool EnterGameRsp(RECV_PACKAGE& package);
	bool LeaveGameRsp(RECV_PACKAGE& package);
	bool NotifyChangeLogic(RECV_PACKAGE& package);
	bool LogicKickPlayer(RECV_PACKAGE& package);

	bool CharLstReqToDB(uint32_t zid, uint32_t uid, uint32_t reqid);
	bool CharLstRspFromDB(RECV_PACKAGE& package);

	// recv chardb and send client
	bool CreateCharacterRsp(RECV_PACKAGE& package);
	bool DelCharacterRsp(RECV_PACKAGE& package);
	bool DelCharacterCancelRsp(RECV_PACKAGE& package);
	bool CharDBToCharSimpleDB(CharacterDBInfo* pCharInfo, CharacterDBSimpleInfo* charSimpleInfo);

	//log 
	void PlayerCreateLog(uint32_t uid, CharIDType cid, uint32_t channelId, const CharacterDBSimpleInfo& charSimpleInfo);
	void PlayerDelCharacterLog(uint32_t uid, CharIDType cid, uint32_t channelId, string cName);
	void PlayerDelCancelCharacterLog(uint32_t uid, CharIDType cid, uint32_t channelId, string cName);

public:
	bool Init();
	bool UnInit();
	void Update(uint64_t tick);
	void SetLoginOpen(bool open) { m_bloginOpen = open; }
	UidGameInfo* GetUidGameInfo(uint32_t clientId);
	UidGameInfo* GetUidGameInfoByCid(CharIDType cid);
	uint32_t	GetClientId(uint32_t uid);
	uint32_t	GetLogoutClientId(uint32_t uid);

	uint32_t GetClientIdByCid(CharIDType cid);
	uint32_t GetLogicIdByCid(CharIDType cid);
	//获取在线玩家，去掉离线和登出的
	void	 GetClientLst(MAP_UINT32_LST_UINT32& outClientIds, SET_UINT64& setChars);

	bool GateChangeLogic(uint32_t clientId, uint32_t ctype, uint32_t logicId, bool force = false, LOGOUT_FLAG flag = LOGOUT_FLAG_NORMAL);
	bool NotifyLogicLeave(CharIDType cid, uint32_t uid, uint32_t clientId, uint32_t logicId, LOGOUT_TYPE type = LOGOUT_TYPE_NONE);
	void OnChangeScene(CharIDType cid, uint32_t clientId, uint32_t uid, uint32_t logicId);
	bool OnPrepareChangeScene(CharIDType cid, uint32_t clientId, uint32_t uid, uint32_t logicId);

	virtual void		onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package);
	virtual const char* getDBProxyHandlerDebugInfo(void) { return nullptr; };

	virtual void		onServerMessage(uint32_t actionId, RECV_PACKAGE &package);
	virtual const char* getServerHandlerDebugInfo(void){ return nullptr;};

	virtual void        onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id = 0);;
	virtual const char* getClientHandlerDebugInfo(void){ return nullptr;};

	bool DisConnect(RECV_PACKAGE& package);

	bool				Logout(uint32_t clientId,uint64_t cid);
	bool				Leave(UidGameInfo& uidInfo, bool isKick, uint64_t cid);
	//中心服踢角色 accountUid:账号UID
	//isCheatFlag  true表示作弊被T
	bool KickAccount(uint64_t accountUid,bool isCheatFlag=false);
	bool KickAllAccount();

	//逻辑服崩溃
	void LogicCrash(uint32_t logicId);
	//玩家登录中心服玩家相关的属性数据
	void CharLoginCenterData(CharIDType charId,CharLoginSyncCenterData &centerData);
	//是否所有的预加载都完成了
	bool IsAllPreLoadFinished();
	//获取在线的cid列表
	void GetOnlineCidQueue(std::queue<CharIDType>& cidLst);

	CenterAccountMgr();
	~CenterAccountMgr();
};

#define g_MakeCenterAccountMgr() (CenterAccountMgr::Instance())
#define g_GetCenterAccountMgr()  (CenterAccountMgr::GetInstance())
#define g_DelCenterAccountMgr()  (CenterAccountMgr::Destroy())